package com.hotel.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.mysql.jdbc.Statement;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;

/**
 * @Author Str
 * @Date 2021/10/28 18:53
 * @Description :
 * [1] 把参数保存至 mysql.properties 文件
 * [2] 在 JdbcUtil 中加载这些数据。
 * [3] 引入 QueryRunner 工具。
 * [4] 编写三个方法。
 */
public class JdbcUtils {
    //{1}设置druid连接池
    public static DruidDataSource dataSource;

    //{ps}设置了静态初始化块
    //    用来加载 mysql 驱动类字节文件。
    //1.初始化Druid连接池
    static {
        InputStream is = null;
        try {
            Properties properties = new Properties();
            //{1}获取类加载器
            ClassLoader loader = JdbcUtils.class.getClassLoader();
            //{2}这个方法可以获取 \WEB-INF\classes 目录下某文件输入流。
            is = loader.getResourceAsStream("druid.properties");
            properties.load(is);
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    //{ps}每一次去使用数据库时, 直接调用该方法即可。
    //2.获取连接
    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }


    //3.关闭连接
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void closeConnection() {
        try {
            Connection conn = getConnection();
            if (conn != null) {
                //{2}关闭连接..
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    public static void setParas(PreparedStatement ps, int start, Object... args) throws SQLException {
        int index = start;
        for (Object obj : args) {
            ps.setObject(index++, obj);
        }
    }

    public static void closeResource(AutoCloseable... res) throws Exception {
        for (AutoCloseable re : res) {
            re.close();
        }
    }

    //{1}定义一个 QueryRunner
    //   它是一个数据查询器与 SQL 执行器。
    private static final QueryRunner QR = new QueryRunner();

    //{2}功能: 查询一个单体对象(User)
    public static <E> E queryObject(String sql, Class<E> clazz, Object... args) {
        Connection conn = null;
        E e = null;
        try {
            //{1}获取连接对象
            conn = getConnection();
            //{2}调用查询方法, 查出一个对象
            e = QR.query(conn, sql, new BeanHandler<E>(clazz), args);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return e;
    }

    //{2}查询头一列(字段)单值的方法 [如: 记录数]
    public static Object queryValue(String sql, Object... args) throws SQLException {
        //{1}获取连接对象
        Connection conn = getConnection();
        //{2}执行一个单值查询
        return QR.query(conn, sql, new ScalarHandler(), args);
    }

    //{1}查询列表的方法
    public static <E> List<E> queryList(String sql, Class<E> clazz, Object... args) throws SQLException {
        Connection conn = getConnection();
        List<E> list = QR.query(conn, sql, new BeanListHandler<E>(clazz), args);
        return list;
    }

    //{1}适用于 insert into, delete, update [三个操作]
    public static int update(String sql, Object... args) throws SQLException {
        Connection conn = getConnection();
        int ret = QR.update(conn, sql, args);
        return ret;
    }
}
